package com.taa.infrastructure.adapter.repository;

import com.taa.domain.trade.adapter.repository.ITradeRepository;
import com.taa.domain.trade.model.entity.OrderEntity;
import com.taa.domain.trade.model.entity.ProductEntity;
import com.taa.domain.trade.model.entity.UserEntity;
import com.taa.infrastructure.dao.*;
import com.taa.infrastructure.dao.po.*;
import com.taa.infrastructure.redis.IRedisService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @Author: taa
 * @Desc: 交易仓储层
 * @Create: 2025-06-01 19:13
 **/
@Slf4j
@Repository
public class TradeRepository implements ITradeRepository {

    @Resource
    private IUserDao userDao;
    @Resource
    private IOrderDao orderDao;
    @Resource
    private IOrderItemDao orderItemDao;
    @Resource
    private IProductDao productDao;
    @Resource
    private IStrategyDao strategyDao;
    @Resource
    private IProductStrategyDao productStrategyDao;
    @Resource
    private IRedisService redisService;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Value("${spring.rabbitmq.topic.stock_update}")
    private String topic;

    @Override
    public int queryUserStatus(String userName) {
        User user = userDao.selectByUserName(userName);
        return user.getStatus();
    }

    @Override
    public int queryStockByProductId(Long productId) {
        Product product = productDao.selectById(productId);
        return product.getStock();
    }

    @Override
    public void fillProductStrategy(List<ProductEntity> productEntityList) {
        for (ProductEntity productEntity : productEntityList) {
            Long productId = productEntity.getProductId();
            List<Long> strategyIdList = productStrategyDao.selectByProductId(productId);
            if (strategyIdList == null || strategyIdList.isEmpty()) {
                continue;
            }
            for (Long strategyId : strategyIdList) {
                Strategy strategy = strategyDao.selectById(strategyId);
                productEntity.setStrategyEntityList(new ArrayList<>());
                productEntity.getStrategyEntityList().add(ProductEntity.StrategyEntity.builder()
                        .strategyName(strategy.getStrategyName())
                        .strategyValue(strategy.getStrategyValue())
                        .build());
            }
        }
    }

    @Override
    public boolean reduceStock(List<Long> productIdList) {
        List<Long> deductedProductIds = new ArrayList<>();
        for (Long productId : productIdList) {
            deductedProductIds.add(productId);
            String key = "product_" + productId + "_stock";

            if (!redisService.isExists(key)) {
                Product product = productDao.selectById(productId);
                redisService.setAtomicLong(key, product.getStock());
            }
            long surplus = redisService.decr(key);
            if (surplus < 0) {
                for (Long deductedProductId : deductedProductIds) {
                    String deductedKey = "product_" + deductedProductId + "_stock";
                    redisService.incr(deductedKey);
                }
                return false;
            }
        }
        rabbitTemplate.convertAndSend(topic, productIdList);
        return true;
    }

    @Override
    public boolean updateStock(List<Long> productIdList) {
        try {
            Boolean result = transactionTemplate.execute(status -> {
                for (Long productId : productIdList) {
                    String key = "product_" + productId + "_stock";
                    int value = redisService.getAtomicLong(key).intValue();

                    int count = productDao.updateStock(productId, value);
                    if (count != 1) {
                        status.setRollbackOnly();
                        log.error("更新商品库存失败 productId:{}", productId);
                        throw new RuntimeException("更新商品库存失败，productId: " + productId);
                    }
                }
                return true;
            });
            return Boolean.TRUE.equals(result); // 确保不为 null

        } catch (Exception e) {
            log.error("库存更新事务回滚", e);
            return false;
        }
    }

    @Override
    public OrderEntity generateOrder(String userName, List<ProductEntity> productEntityList, BigDecimal totalOriginalPrice, BigDecimal totalDiscountPrice) {
        String orderNo = RandomStringUtils.randomNumeric(12);
        Order order = new Order();

        order.setOrderNo(orderNo);
        order.setUserId(userDao.selectByUserName(userName).getId());
        order.setTotalAmount(totalOriginalPrice);
        order.setPayAmount(totalDiscountPrice);
        order.setStatus(0);
        orderDao.insert(order);

        for (ProductEntity productEntity : productEntityList) {
            
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderNo(orderNo);
            orderItem.setProductId(productEntity.getProductId());
            orderItem.setProductName(productEntity.getProductName());
            orderItem.setProductPrice(productEntity.getOriginalPrice());
            orderItem.setDiscountPrice(productEntity.getDiscountPrice());
            orderItemDao.insertOrderItem(orderItem);
            
        }

        return OrderEntity.builder()
                .orderNo(orderNo)
                .userId(userDao.selectByUserName(userName).getId())
                .totalAmount(totalOriginalPrice)
                .payAmount(totalDiscountPrice)
                .status(0)
                .productEntityList(productEntityList)
                .build();
    }

    @Override
    public List<ProductEntity> listProducts() {
        List<Product> productList = productDao.selectAll();
        if (productList == null || productList.isEmpty()) {
            return null;
        }
        List<ProductEntity> productEntityList = new ArrayList<>();
        for (Product product : productList) {
            productEntityList.add(ProductEntity.builder()
                    .productId(product.getId())
                    .productName(product.getProductName())
                    .productDesc(product.getProductDesc())
                    .originalPrice(product.getPrice())
                    .status(product.getStatus())
                    .build());
        }
        return productEntityList;
    }

    @Override
    public UserEntity queryUserByUserName(String userName) {
        User user = userDao.selectByUserName(userName);
        if (user == null) return null;
        return UserEntity.builder()
                .userName(user.getUserName())
                .password(user.getPassword())
                .build();
    }

    @Override
    public List<OrderEntity> queryOrderByUserName(String userName) {
        List<OrderEntity> orderEntityList = new ArrayList<>();
        List<Order> orderList = orderDao.selectByUserId(userDao.selectByUserName(userName).getId());
        if (orderList == null || orderList.isEmpty()) {
            return orderEntityList;
        }

        for (Order order : orderList) {
            List<ProductEntity> productEntityList = new ArrayList<>();
            List<OrderItem> orderItemList = orderItemDao.queryOrderItemByOrderNo(order.getOrderNo());
            for (OrderItem orderItem : orderItemList) {
                Product product = productDao.selectById(orderItem.getProductId());
                productEntityList.add(ProductEntity.builder()
                        .productId(product.getId())
                        .productName(product.getProductName())
                        .productDesc(product.getProductDesc())
                        .originalPrice(product.getPrice())
                        .status(product.getStatus())
                        .build());
            }
            orderEntityList.add(OrderEntity.builder()
                    .orderNo(order.getOrderNo())
                    .userId(order.getUserId())
                    .totalAmount(order.getTotalAmount())
                    .payAmount(order.getPayAmount())
                    .status(order.getStatus())
                    .productEntityList(productEntityList)
                    .build());
        }

        return orderEntityList;
    }
}

